#include <iostream>
using namespace std;

class Object {};

int main() {
  int *p1;
  int* p2, i; // i是int而非指针
  int& r = i, j; // r是整型引用，j是int
  int*& rp = p2; // 整型指针的引用
//int&* pr = &r; // 错误！不能定义指向引用的指针
  int a[0]; // 数组（长度可以是0）
  delete[] new int[1]; // new T[]一定对应delete[]，即使长度为1或0。
  const int * cp1; // const在*的左边，常量指针，所指目标视为常量不能修改。
  int const * cp2; // 同上
  int * const pc3 = &i; // const在*的右边，指针常量，定义时就要初始化并且不能指向其他目标。
  int const * const cpc = &i; // 常量指针常量，指针的指向和目标内容都不能修改。
  Object fo(); // 函数声明，不是变量定义，也不是函数调用（因为有返回类型）
  Object oa, ob{}; // 想用无参构造函数，不加括号，或用大括号。
  int *ap[2]; // []比*更优先，是指针数组。
  int *fa(); // ()比*更优先，是函数声明，这函数返回int指针。
  int (*pa)[2]; // 加括号使pa首先与左侧*结合，指向整型数组，是数组指针。
  int (*pf)();  // 加括号使pf首先与左侧*结合，指向无参且返回int的函数，是函数指针。
  int (*afp1[2])(); // 先与右边[]结合，T[]是种数组。
                    // (*T[])被圆括号包围，数组的元素是某种指针。
                    // 外围int (T)()是函数，即数组元素是函数指针，指向无参且返回int的函数。
  int*(*afp2[2])(int*); // 与上面类似，数组元素是函数指针，指向参数和返回值都是整型指针的函数。
  void (*signal(int sig, void (*func)(int)))(int);
  // 从*signal(... 名字signal先与右侧(结合，是函数声明。
  // 参数列表是：int sig, void (*func)(int) 有两个参数，第二个参数是函数指针，指向有一个整型参数但无返回值的函数。
  // 返回类型是：void (*)(int) 返回函数指针，指向有一个整型参数但无返回值的函数。
}


